/*
 * SuperChatView.java
 */
package superchat;

import org.jdesktop.application.Action;
import org.jdesktop.application.ResourceMap;
import org.jdesktop.application.SingleFrameApplication;
import org.jdesktop.application.FrameView;
import org.jdesktop.application.TaskMonitor;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.net.Socket;
import javax.swing.Timer;
import javax.swing.Icon;
import javax.swing.JDialog;
import javax.swing.JFrame;
import java.util.*;
import javax.swing.DefaultListModel;
import javax.swing.JTextArea;
import org.json.JSONArray;
import org.json.JSONObject;

/**
 * Classe client
 */
public class SuperChatView extends FrameView {

    /**
     * Constructeur de la fenêtre principale
     * @param app 
     */
    public SuperChatView(SingleFrameApplication app) {
        super(app);

        initComponents();

        // status bar initialization - message timeout, idle icon and busy animation, etc
        ResourceMap resourceMap = getResourceMap();
        int messageTimeout = resourceMap.getInteger("StatusBar.messageTimeout");
        messageTimer = new Timer(messageTimeout, new ActionListener() {

            public void actionPerformed(ActionEvent e) {
                statusMessageLabel.setText("");
            }
        });
        messageTimer.setRepeats(false);
        int busyAnimationRate = resourceMap.getInteger("StatusBar.busyAnimationRate");
        for (int i = 0; i < busyIcons.length; i++) {
            busyIcons[i] = resourceMap.getIcon("StatusBar.busyIcons[" + i + "]");
        }
        busyIconTimer = new Timer(busyAnimationRate, new ActionListener() {

            public void actionPerformed(ActionEvent e) {
                busyIconIndex = (busyIconIndex + 1) % busyIcons.length;
                statusAnimationLabel.setIcon(busyIcons[busyIconIndex]);
            }
        });
        idleIcon = resourceMap.getIcon("StatusBar.idleIcon");
        statusAnimationLabel.setIcon(idleIcon);
        progressBar.setVisible(false);

        // connecting action tasks to status bar via TaskMonitor
        TaskMonitor taskMonitor = new TaskMonitor(getApplication().getContext());
        taskMonitor.addPropertyChangeListener(new java.beans.PropertyChangeListener() {

            public void propertyChange(java.beans.PropertyChangeEvent evt) {
                String propertyName = evt.getPropertyName();
                if ("started".equals(propertyName)) {
                    if (!busyIconTimer.isRunning()) {
                        statusAnimationLabel.setIcon(busyIcons[0]);
                        busyIconIndex = 0;
                        busyIconTimer.start();
                    }
                    progressBar.setVisible(true);
                    progressBar.setIndeterminate(true);
                } else if ("done".equals(propertyName)) {
                    busyIconTimer.stop();
                    statusAnimationLabel.setIcon(idleIcon);
                    progressBar.setVisible(false);
                    progressBar.setValue(0);
                } else if ("message".equals(propertyName)) {
                    String text = (String) (evt.getNewValue());
                    statusMessageLabel.setText((text == null) ? "" : text);
                    messageTimer.restart();
                } else if ("progress".equals(propertyName)) {
                    int value = (Integer) (evt.getNewValue());
                    progressBar.setVisible(true);
                    progressBar.setIndeterminate(false);
                    progressBar.setValue(value);
                }
            }
        });
        modelUserList = new DefaultListModel();
        userList.setModel(modelUserList);
        userList.addMouseListener(new ActionJList(userList, this));
        
    }
    /**
     * Affiche la fenêtre "A propos"
     */
    @Action
    public void showAboutBox() {
        if (aboutBox == null) {
            JFrame mainFrame = SuperChatApp.getApplication().getMainFrame();
            aboutBox = new SuperChatAboutBox(mainFrame);
            aboutBox.setLocationRelativeTo(mainFrame);
        }
        SuperChatApp.getApplication().show(aboutBox);
    }

    /**
     * Affiche la fenêtre de choix de login
     */
    @Action
    public void showNickPrompt() {
        if (nickPrompt == null) {
            JFrame mainFrame = SuperChatApp.getApplication().getMainFrame();
            nickPrompt = new SuperChatNickPrompt(mainFrame, true, param, this);
            nickPrompt.setLocationRelativeTo(mainFrame);
        }
        SuperChatApp.getApplication().show(nickPrompt);
    }
    
    /**
     * Ouvre la fenêtre de séléction de fichier/dossier
     * @param selectMode Vrai pour séléctionner un fichier faux pour séléctionner un dossier
     * @param message Message à envoyer au serveur après séléction du fichier
     */
    @Action
    public void showFileSelector(boolean selectMode, String message) {
        if (fileSelector == null) {
            JFrame mainFrame = SuperChatApp.getApplication().getMainFrame();
            fileSelector = new SuperChatFileSelector(mainFrame, true, this, selectMode, message);
            fileSelector.setLocationRelativeTo(mainFrame);
        }
        SuperChatApp.getApplication().show(fileSelector);
    }

    /**
     * Affiche une boite de dialogue contenant un message d'alerte
     * @param message Le message à afficher
     */
    public void alert(String message) {
        if (alertBox == null) {
            JFrame mainFrame = SuperChatApp.getApplication().getMainFrame();
            alertBox = new SuperChatAlert(mainFrame, true, message);
            alertBox.setLocationRelativeTo(mainFrame);
        }
        alertBox.setMessage(message);
        SuperChatApp.getApplication().show(alertBox);
    }

    /**
     * Ajoute un message au salon principal
     * @param author L'auteur du message
     * @param message Le message à afficher
     */
    @Action
    public void add_message(String author, String message) {
        add_line(Main_chat_view, "<"+author+"> : " + message);
        return;
    }
    
    /**
     * Affiche un message de type privé
     * @param chan Le nom du canal, soit le nom de l'utilisateur avec qui on converse
     * @param author L'auteur du message
     * @param message Le message à afficher
     */
    @Action
    public void add_private_message(String chan, String author, String message) {
        if(!chans.containsKey(chan)) add_chan(chan);
        add_line(chans.get(chan), "<"+author+"> : " + message);
    }

    /**
     * Ouvre un onglet de chat
     * @param chan Le nom de l'onglet
     */
    @Action
    public void add_chan(String chan) {
        if(!chan.equals(param.nickname) && !chans.containsKey(chan)) {
            JTextArea list = (JTextArea) this.messagesView.add(chan, new javax.swing.JTextArea());
            list.setEditable(false);
            this.chans.put(chan, list);
            this.messagesView.add(chan, list);
            messagesView.setSelectedComponent(list);
            buttonSendFile.setEnabled(connected && messagesView.getSelectedIndex() > 0);
        }
    }
    
    /**
     * Ajoute du texte à une JTextarea
     * @param zone La zone de texte
     * @param line La ligne de texte à afficher
     */
    public void add_line(javax.swing.JTextArea zone, String line ){
        zone.setText(zone.getText()+line+'\n');
        zone.setCaretPosition(zone.getDocument().getLength());
        if(buttonToggleBip.getState()) java.awt.Toolkit.getDefaultToolkit().beep();
    }
    
    /**
     * Actualise l'interface utilisateur en fonction de la connexion
     * @param o Etat de la connexion
     */
    public void set_connected(boolean o) {
        connected = o;
        this.editMessage.setEnabled(o);
        this.jButton1.setEnabled(o);
        if (o) {
            this.connectMenuItem.setText("Déconnexion");
            add_message("Serveur", "Vous êtes connecté à " + param.ipAdress + ":" + param.port);
        } else {
            modelUserList.clear();
            add_message("Serveur", "Vous avez été déconnecté");
            this.connectMenuItem.setText("Connexion");
        }
    }

    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        mainPanel = new javax.swing.JPanel();
        jButton1 = new javax.swing.JButton();
        editMessage = new javax.swing.JTextField();
        jSplitPane1 = new javax.swing.JSplitPane();
        messagesView = new javax.swing.JTabbedPane();
        mainChat = new javax.swing.JPanel();
        jScrollPane2 = new javax.swing.JScrollPane();
        Main_chat_view = new javax.swing.JTextArea();
        jScrollPane1 = new javax.swing.JScrollPane();
        jList1 = new javax.swing.JList();
        jScrollPane3 = new javax.swing.JScrollPane();
        userList = new javax.swing.JList();
        menuBar = new javax.swing.JMenuBar();
        javax.swing.JMenu fileMenu = new javax.swing.JMenu();
        buttonToggleBip = new javax.swing.JCheckBoxMenuItem();
        javax.swing.JMenuItem exitMenuItem = new javax.swing.JMenuItem();
        jMenu1 = new javax.swing.JMenu();
        connectMenuItem = new javax.swing.JMenuItem();
        buttonSendFile = new javax.swing.JMenuItem();
        javax.swing.JMenu helpMenu = new javax.swing.JMenu();
        javax.swing.JMenuItem aboutMenuItem = new javax.swing.JMenuItem();
        statusPanel = new javax.swing.JPanel();
        javax.swing.JSeparator statusPanelSeparator = new javax.swing.JSeparator();
        statusMessageLabel = new javax.swing.JLabel();
        statusAnimationLabel = new javax.swing.JLabel();
        progressBar = new javax.swing.JProgressBar();

        mainPanel.setName("mainPanel"); // NOI18N

        org.jdesktop.application.ResourceMap resourceMap = org.jdesktop.application.Application.getInstance(superchat.SuperChatApp.class).getContext().getResourceMap(SuperChatView.class);
        jButton1.setText(resourceMap.getString("jButton1.text")); // NOI18N
        jButton1.setEnabled(false);
        jButton1.setName("jButton1"); // NOI18N
        jButton1.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jButton1ActionPerformed(evt);
            }
        });

        editMessage.setText(resourceMap.getString("message.text")); // NOI18N
        editMessage.setEnabled(false);
        editMessage.setName("message"); // NOI18N
        editMessage.addKeyListener(new java.awt.event.KeyAdapter() {
            public void keyReleased(java.awt.event.KeyEvent evt) {
                editMessageKeyReleased(evt);
            }
        });

        jSplitPane1.setName("jSplitPane1"); // NOI18N

        messagesView.setName("messagesView"); // NOI18N
        messagesView.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mouseClicked(java.awt.event.MouseEvent evt) {
                messagesViewMouseClicked(evt);
            }
        });

        mainChat.setName("mainChat"); // NOI18N

        jScrollPane2.setName("jScrollPane2"); // NOI18N

        Main_chat_view.setColumns(20);
        Main_chat_view.setEditable(false);
        Main_chat_view.setLineWrap(true);
        Main_chat_view.setRows(5);
        Main_chat_view.setName("Main_chat_view"); // NOI18N
        jScrollPane2.setViewportView(Main_chat_view);

        javax.swing.GroupLayout mainChatLayout = new javax.swing.GroupLayout(mainChat);
        mainChat.setLayout(mainChatLayout);
        mainChatLayout.setHorizontalGroup(
            mainChatLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addComponent(jScrollPane2, javax.swing.GroupLayout.DEFAULT_SIZE, 391, Short.MAX_VALUE)
        );
        mainChatLayout.setVerticalGroup(
            mainChatLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addComponent(jScrollPane2, javax.swing.GroupLayout.DEFAULT_SIZE, 361, Short.MAX_VALUE)
        );

        messagesView.addTab(resourceMap.getString("mainChat.TabConstraints.tabTitle"), mainChat); // NOI18N

        jSplitPane1.setLeftComponent(messagesView);

        jScrollPane1.setName("jScrollPane1"); // NOI18N

        jList1.setName("jList1"); // NOI18N
        jScrollPane1.setViewportView(jList1);

        jSplitPane1.setRightComponent(jScrollPane1);

        jScrollPane3.setName("jScrollPane3"); // NOI18N

        userList.setSelectionMode(javax.swing.ListSelectionModel.SINGLE_SELECTION);
        userList.setName("userList"); // NOI18N
        jScrollPane3.setViewportView(userList);

        jSplitPane1.setRightComponent(jScrollPane3);

        javax.swing.GroupLayout mainPanelLayout = new javax.swing.GroupLayout(mainPanel);
        mainPanel.setLayout(mainPanelLayout);
        mainPanelLayout.setHorizontalGroup(
            mainPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(mainPanelLayout.createSequentialGroup()
                .addContainerGap()
                .addGroup(mainPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(jSplitPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 748, Short.MAX_VALUE)
                    .addGroup(mainPanelLayout.createSequentialGroup()
                        .addComponent(editMessage, javax.swing.GroupLayout.DEFAULT_SIZE, 659, Short.MAX_VALUE)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(jButton1)))
                .addContainerGap())
        );
        mainPanelLayout.setVerticalGroup(
            mainPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, mainPanelLayout.createSequentialGroup()
                .addContainerGap()
                .addComponent(jSplitPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 390, Short.MAX_VALUE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(mainPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(jButton1)
                    .addComponent(editMessage, javax.swing.GroupLayout.PREFERRED_SIZE, 24, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addContainerGap())
        );

        menuBar.setName("menuBar"); // NOI18N

        fileMenu.setText(resourceMap.getString("fileMenu.text")); // NOI18N
        fileMenu.setName("fileMenu"); // NOI18N

        buttonToggleBip.setSelected(true);
        buttonToggleBip.setText(resourceMap.getString("buttonToggleBip.text")); // NOI18N
        buttonToggleBip.setName("buttonToggleBip"); // NOI18N
        fileMenu.add(buttonToggleBip);

        javax.swing.ActionMap actionMap = org.jdesktop.application.Application.getInstance(superchat.SuperChatApp.class).getContext().getActionMap(SuperChatView.class, this);
        exitMenuItem.setAction(actionMap.get("quit")); // NOI18N
        exitMenuItem.setText(resourceMap.getString("exitMenuItem.text")); // NOI18N
        exitMenuItem.setToolTipText(resourceMap.getString("exitMenuItem.toolTipText")); // NOI18N
        exitMenuItem.setName("exitMenuItem"); // NOI18N
        fileMenu.add(exitMenuItem);

        menuBar.add(fileMenu);

        jMenu1.setText(resourceMap.getString("jMenu1.text")); // NOI18N
        jMenu1.setName("jMenu1"); // NOI18N

        connectMenuItem.setText(resourceMap.getString("connectMenuItem.text")); // NOI18N
        connectMenuItem.setName("connectMenuItem"); // NOI18N
        connectMenuItem.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                connectMenuItemActionPerformed(evt);
            }
        });
        jMenu1.add(connectMenuItem);

        buttonSendFile.setText(resourceMap.getString("sendFile.text")); // NOI18N
        buttonSendFile.setEnabled(false);
        buttonSendFile.setName("sendFile"); // NOI18N
        buttonSendFile.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                buttonSendFileActionPerformed(evt);
            }
        });
        jMenu1.add(buttonSendFile);

        menuBar.add(jMenu1);

        helpMenu.setText(resourceMap.getString("helpMenu.text")); // NOI18N
        helpMenu.setName("helpMenu"); // NOI18N

        aboutMenuItem.setAction(actionMap.get("showAboutBox")); // NOI18N
        aboutMenuItem.setText(resourceMap.getString("aboutMenuItem.text")); // NOI18N
        aboutMenuItem.setName("aboutMenuItem"); // NOI18N
        helpMenu.add(aboutMenuItem);

        menuBar.add(helpMenu);

        statusPanel.setName("statusPanel"); // NOI18N

        statusPanelSeparator.setName("statusPanelSeparator"); // NOI18N

        statusMessageLabel.setName("statusMessageLabel"); // NOI18N

        statusAnimationLabel.setHorizontalAlignment(javax.swing.SwingConstants.LEFT);
        statusAnimationLabel.setName("statusAnimationLabel"); // NOI18N

        progressBar.setName("progressBar"); // NOI18N

        javax.swing.GroupLayout statusPanelLayout = new javax.swing.GroupLayout(statusPanel);
        statusPanel.setLayout(statusPanelLayout);
        statusPanelLayout.setHorizontalGroup(
            statusPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addComponent(statusPanelSeparator, javax.swing.GroupLayout.DEFAULT_SIZE, 772, Short.MAX_VALUE)
            .addGroup(statusPanelLayout.createSequentialGroup()
                .addContainerGap()
                .addComponent(statusMessageLabel)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 748, Short.MAX_VALUE)
                .addComponent(statusAnimationLabel)
                .addContainerGap())
            .addGroup(statusPanelLayout.createSequentialGroup()
                .addContainerGap()
                .addComponent(progressBar, javax.swing.GroupLayout.PREFERRED_SIZE, 98, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addContainerGap(662, Short.MAX_VALUE))
        );
        statusPanelLayout.setVerticalGroup(
            statusPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(statusPanelLayout.createSequentialGroup()
                .addComponent(statusPanelSeparator, javax.swing.GroupLayout.PREFERRED_SIZE, 2, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                .addGroup(statusPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(statusMessageLabel)
                    .addComponent(statusAnimationLabel)
                    .addComponent(progressBar, javax.swing.GroupLayout.PREFERRED_SIZE, 14, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addGap(3, 3, 3))
        );

        setComponent(mainPanel);
        setMenuBar(menuBar);
        setStatusBar(statusPanel);
    }// </editor-fold>//GEN-END:initComponents

    /**
     * Envoi du message lors du clic sur le bouton "Envoyer message"
     * @param evt 
     */
    private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton1ActionPerformed
        this.sendMessage(editMessage.getText());
    }//GEN-LAST:event_jButton1ActionPerformed

    /**
     * Envoi du message lors de l'appui sur la touche entrée
     * @param evt 
     */
    private void editMessageKeyReleased(java.awt.event.KeyEvent evt) {//GEN-FIRST:event_editMessageKeyReleased
       if(evt.getKeyCode()==java.awt.event.KeyEvent.VK_ENTER){
            this.sendMessage(editMessage.getText());
        }
    }//GEN-LAST:event_editMessageKeyReleased

    /**
     * Déconnecte ou connecte l'utilisateur lors du clic sur Action/(dé)connexion
     * @param evt 
     */
    private void connectMenuItemActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_connectMenuItemActionPerformed
        if(connected) {
            try {
                this.com.socket.close();
                this.com = null;
                set_connected(false);
                add_message("Serveur", "Vous avez été déconnecté.");
            } catch (Exception ex) {
                alert("Erreur lors de la déconnexion");
            }
        }
        else showNickPrompt();
    }//GEN-LAST:event_connectMenuItemActionPerformed

    /**
     * Fonction appelée lorsque l'on clique sur "envoyer un fichier"
     * @param evt 
     */
    private void buttonSendFileActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonSendFileActionPerformed
        // TODO add your handling code here:
        showFileSelector(true, null);
    }//GEN-LAST:event_buttonSendFileActionPerformed

    /**
     * Update l'interface lorsque l'on clique sur un onglet pour savoir si un chat privé est ouvert
     * @param evt 
     */
    private void messagesViewMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_messagesViewMouseClicked
        buttonSendFile.setEnabled(connected && messagesView.getSelectedIndex() > 0);
    }//GEN-LAST:event_messagesViewMouseClicked

    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JTextArea Main_chat_view;
    private javax.swing.JMenuItem buttonSendFile;
    private javax.swing.JCheckBoxMenuItem buttonToggleBip;
    private javax.swing.JMenuItem connectMenuItem;
    private javax.swing.JTextField editMessage;
    private javax.swing.JButton jButton1;
    private javax.swing.JList jList1;
    private javax.swing.JMenu jMenu1;
    private javax.swing.JScrollPane jScrollPane1;
    private javax.swing.JScrollPane jScrollPane2;
    private javax.swing.JScrollPane jScrollPane3;
    private javax.swing.JSplitPane jSplitPane1;
    private javax.swing.JPanel mainChat;
    private javax.swing.JPanel mainPanel;
    private javax.swing.JMenuBar menuBar;
    private javax.swing.JTabbedPane messagesView;
    private javax.swing.JProgressBar progressBar;
    private javax.swing.JLabel statusAnimationLabel;
    private javax.swing.JLabel statusMessageLabel;
    private javax.swing.JPanel statusPanel;
    private javax.swing.JList userList;
    // End of variables declaration//GEN-END:variables
    private final Timer messageTimer;
    private final Timer busyIconTimer;
    private final Icon idleIcon;
    private final Icon[] busyIcons = new Icon[15];
    private int busyIconIndex = 0;
    private SuperChatAlert alertBox;
    private JDialog aboutBox;
    private JDialog nickPrompt;
    private JDialog fileSelector;
    private Communication com;
    private Param param = new Param();
    private HashMap<String, JTextArea> chans = new HashMap<String, JTextArea>();
    private HashMap<String, FileBuffer> fileBuffers = new HashMap<String, FileBuffer>();
    private DefaultListModel modelUserList;
    private boolean connected = false;

    /**
     * Initialise la connexion avec le serveur
     * @param port Port pour communication
     * @param pseudo Pseudo de l'utilisateur
     * @param ip Ip du serveur
     */
    public void connexion(int port, String pseudo, String ip) {
        JSONObject x = new JSONObject();
        try {
            this.com = new Communication(new Socket(param.ipAdress, param.port), this);
            x.put("action", 0);
            x.put("pseudo", pseudo);
            String sended = x.toString();
            this.com.out.writeUTF(sended);
            if (nickPrompt != null) {
                nickPrompt.setVisible(false);
                set_connected(true);
            }
            this.com.start();
        } catch (Exception ex) {
            alert("Connexion impossible !");
        }
        

    }
    
    /**
     * Fonction appelée par la fenêtre de sélection du fichier, envoi une demande de transfert de fichier au serveur
     * @param filename Chemin du fichier à envoyer
     */
    void requestFileSend(String filename) {
        try {
            JSONObject m = new JSONObject();
            m.put("action", 3);
            m.put("destinataire", messagesView.getTitleAt(messagesView.getSelectedIndex()));
            m.put("filename", filename);
            com.out.writeUTF(m.toString());
        } catch (Exception ex) {
            alert("Erreur requête envoi fichier");
        }
    }
    
    /**
     * Envoi du message au serveur, si l'utilisateur est dans un canal privé, le message sera envoyé comme un message privé
     * @param msg Le texte du message à envoyer
     */
    void sendMessage(String msg){
        if(!msg.equals("")) {
            JSONObject x = new JSONObject();
            try {
                x.put("message", msg);
                if(messagesView.getSelectedIndex() > 0) {
                    String destinataire = messagesView.getTitleAt(messagesView.getSelectedIndex());
                    x.put("action", 2);
                    x.put("destinataire", destinataire);
                    if(modelUserList.contains(destinataire)) {
                        add_private_message(destinataire, param.nickname, msg);
                        com.out.writeUTF(x.toString());
                    }
                    else add_private_message(destinataire, "Serveur", destinataire + " est déconnecté, envoi du message impossible.");
                }
                else {
                    x.put("action",1);
                    com.out.writeUTF(x.toString());
                }
                editMessage.setText("");
            } catch (Exception e) {
                alert("Une erreur s'est produite lors de l'envois de message");
            }
        }
    }

    /**
     * Fonction appellée par la fenêtre de choix de destination du fichier, créé un FileBuffer pour la récéption du fichier
     * @param destination Le chemin où enregistrer le fichier
     * @param params Le message à envoyer au serveur pour signifer l'acceptation du transfert
     */
    void acceptFileTransfert(String destination, String params) {
        try {
            JSONObject p = new JSONObject(params);
            String pseudo = p.getString("destinataire");
            String filename = p.getString("filename");
            String[] names = filename.split("/");
            String newPath = destination+"/"+names[names.length-1];
            fileBuffers.put(pseudo+"*"+filename, new FileBuffer(newPath, this));
            com.out.writeUTF(params);
        } catch (Exception ex) {
            alert("Erreur acceptation transfert fichier");
        }
    }
    
    /**
     * Fonction appellée par la classe communication lors de la reception d'un message
     * @param aThis L'objet communication qui a appellé la methode
     */
    void interpretMessage(Communication aThis) {
        JSONObject x = new JSONObject();
        try {
            int action = aThis.message.getInt("action");
            String pseudo;
            String message;
            String filename;
            switch (action) {
                case 400: //Pseudo déjà pris !
                    alert("Pseudo déjà utilisé !");
                    com.socket.close();
                    com = null;
                    set_connected(false);
                    showNickPrompt();
                    break;
                case 55:
                    pseudo = com.message.getString("expediteur");
                    filename = com.message.getString("filename");
                    String block = com.message.getString("block");
                    int nb = com.message.getInt("nb");
                    int m = com.message.getInt("max");
                    fileBuffers.get(pseudo+"*"+filename).push(block, nb, m);
                    break;
                case 54:
                    pseudo = com.message.getString("expediteur");
                    filename = com.message.getString("filename");
                    String dataString = Base64.encodeFromFile(filename);
                    int nbBlocks = (int) Math.ceil((double) dataString.length()/1000);
                    JSONObject send = new JSONObject().put("action", 5).put("max", nbBlocks).put("destinataire", pseudo).put("filename", filename);
                    int i;
                    int max;
                    for(i=0;i<=nbBlocks;i++) {
                        if(((i+1)*1000) > (dataString.length())) max = dataString.length();
                        else max = (i+1)*1000;
                        send.put("nb", i);
                        send.put("block", dataString.substring(i*1000, max));
                        com.out.writeUTF(send.toString());
                    }
                    break;
                case 53:
                    pseudo = com.message.getString("expediteur");
                    filename = com.message.getString("filename");
                    String[] names = filename.split("/");
                    add_private_message(pseudo, "Serveur", pseudo + " vous envoie " + names[names.length-1] + " choisissez la destination.");
                    String messageAccept = new JSONObject().put("action", 4).put("filename", filename).put("destinataire", pseudo).toString();
                    showFileSelector(false, messageAccept);
                    break;
                case 52:
                    pseudo = com.message.getString("expediteur");
                    message = com.message.getString("message");
                    this.add_private_message(pseudo, pseudo, message);
                    break;
                case 51:
                    pseudo = com.message.getString("pseudo");
                    message = com.message.getString("message");
                    this.add_message(pseudo, message);
                    break;
                case 50:
                    JSONArray pseudos = com.message.getJSONArray("pseudos");
                    modelUserList.clear();
                    for(int a=0;a<pseudos.length();a++){
                        modelUserList.add(a, pseudos.getString(a));
                    }
                    break;
            }
        } catch (Exception ex) {
            alert("Erreur lors de l'interprétation du message");
        }

    }

    /**
     * Fonction appelé lors d'une déconnexion de l'objet Communication du client
     * @param aThis 
     */
    void disconnect(Communication aThis) {
        add_message("Serveur", "Connexion avec le serveur perdue");
    }
}
